package top.eggcode.common.finance;

import top.eggcode.common.error.ServiceLogicException;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 算盘
 * 致敬中国古代发明
 * 这里主要是对业务中的计算方法做提炼，解决代码中频繁的数值类型转换
 */
public final class Abacus {

    /**
     * 相加
     *
     * @param leftObj  左边元素
     * @param rightObj 右边元素
     * @return 计算后的数值对象
     */
    public static BigDecimal add(Object leftObj, Object rightObj) {

        BigDecimal leftNum = convert(leftObj);
        BigDecimal rightNum = convert(rightObj);


        return leftNum.add(rightNum);
    }

    /**
     * 相减
     *
     * @param leftObj  左边元素
     * @param rightObj 右边元素
     * @return 计算后的数值对象
     */
    public static BigDecimal subtract(Object leftObj, Object rightObj) {

        BigDecimal leftNum = convert(leftObj);
        BigDecimal rightNum = convert(rightObj);


        return leftNum.subtract(rightNum);
    }

    /**
     * 相乘
     *
     * @param leftObj  左边元素
     * @param rightObj 右边元素
     * @return 计算后的数值对象
     */
    public static BigDecimal multiply(Object leftObj, Object rightObj) {

        BigDecimal leftNum = convert(leftObj);
        BigDecimal rightNum = convert(rightObj);


        return leftNum.multiply(rightNum);
    }

    /**
     * 相除
     *
     * @param leftObj  左边元素
     * @param rightObj 右边元素
     * @return 计算后的数值对象
     */
    public static BigDecimal divide(Object leftObj, Object rightObj) {

        BigDecimal leftNum = convert(leftObj);
        BigDecimal rightNum = convert(rightObj);


        return leftNum.divide(rightNum);
    }

    /**
     * 将不同形式的数值表示转换成 BigDecimal 对象
     * 支持 int、long、float、double、string
     *
     * @param num 任意形式的数值
     * @return 返回小数点对象
     */
    public static BigDecimal convert(Object num) {
        if (num instanceof BigDecimal) {
            return (BigDecimal) num;
        } else if (num instanceof String) {
            return new BigDecimal((String) num);
        } else if (num instanceof Integer) {
            return new BigDecimal((int) num);
        } else if (num instanceof Long) {
            return BigDecimal.valueOf((Long) num);
        } else if (num instanceof Float) {
            return BigDecimal.valueOf((Float) num);
        } else if (num instanceof Double) {
            return BigDecimal.valueOf((Double) num);
        } else {
            throw new ServiceLogicException("The value type is not supported：" + num.getClass());
        }
    }

    public static void main(String[] args) {
        BigDecimal num = Abacus.multiply(7, "9.11")
                .setScale(2, RoundingMode.HALF_UP);
        System.out.println(num);
    }
}
